﻿#define Asynchronous 0
#include <wfcClient.h>
#include <pfcComponentFeat.h>
#include <pfcAsyncConnection.h>

#include "OTKXString.cpp"
#include "logger.cpp"
#include "wxyutils.cpp"

#include <xstring>
#define MSGFILE "MechSim.txt"
// #define ERRFILE "ErrorMsg.txt"
string LogFile[] = {"info.log", "warn.log", "error.log"};
#define TEST_CALL_REPORT(call, from, status, error)                   \
    {                                                                 \
        if (error)                                                    \
            LOG(LOG_ERROR) << call << "\t" << from << "\t" << status; \
    }
#define TEST_CALL_EXIT(error)      \
    {                              \
        if (error)                 \
            return wfcTK_NO_ERROR; \
    }
#define ACTION_TYPE(v, f)    \
    p_visit_action_type = v; \
    p_filter_action_type = f;
const char *ProjectName = "MechSim";
string dllpath;

#ifdef GetMessage
#define GetMessage GetMessage
#endif

#include <wfcModel.h>
class ParamActionListener : public wfcModelParamActionListener
{
    void OnBeforeParameterCreate(pfcModel_ptr Owner,
                                 xrstring Name,
                                 pfcUnit_ptr Units,
                                 pfcParamValue_ptr Value);

    void OnBeforeParameterModify(pfcParameter_ptr Param,
                                 pfcUnit_ptr NewUnits,
                                 pfcParamValue_ptr NewValue,
                                 pfcUnit_ptr OldUnits,
                                 pfcParamValue_ptr OldValue);

    void OnAfterParameterModify(pfcParameter_ptr Param,
                                pfcUnit_ptr NewUnits,
                                pfcParamValue_ptr NewValue,
                                pfcUnit_ptr OldUnits,
                                pfcParamValue_ptr OldValue) {}

    void OnAfterParameterDelete(pfcModel_ptr Owner,
                                xrstring Name,
                                pfcUnit_ptr Units,
                                pfcParamValue_ptr OldValue) {}
};
#include <wfcFeature.h>
class FeatureParamListener : public wfcFeatureParamActionListener
{
    void OnBeforeParameterCreate(pfcFeature_ptr Owner, xrstring Name, pfcUnit_ptr Units, pfcParamValue_ptr Value);

    void OnBeforeParameterModify(pfcParameter_ptr Param, pfcUnit_ptr NewUnits, pfcParamValue_ptr NewValue, pfcUnit_ptr OldUnits, pfcParamValue_ptr OldValue);

    void OnAfterParameterModify(pfcParameter_ptr Param, pfcUnit_ptr NewUnits, pfcParamValue_ptr NewValue, pfcUnit_ptr OldUnits, pfcParamValue_ptr OldValue) {}

    void OnAfterParameterDelete(pfcFeature_ptr Owner, xrstring Name, pfcUnit_ptr Units, pfcParamValue_ptr OldValue) {}
};

int Async_Action(pfcSession_ptr session);
wfcStatus Action();

void cleanlog();
#include <ProSelection.h>
#include <ProMode.h>
#include <ProModelitem.h>
#include <ProToolkitErrors.h>
#include <ProSelection.h>
#include <ProFeature.h>
#include <ProAnalysis.h>
#include <ProWorkspace.h>
#include <ProAnimate.h>
#include <ProArray.h>
#include <ProToolkit.h>
#include <ProAsmcomppath.h>
#include <ProVariantFeat.h>
#include <ProUtil.h>
#define MAX_FRAMES_NUM 1
#define PI 3.14
#define ANI_OBJECT(i, f) (ani_obj_seq[i].anims[f])

typedef struct tag_AniObjectInstance
{
    ProMdl model;                     /* Handle to the animated model */
    ProAsmcomppath comp_path;         /* Component path of the object */
    ProAnimObj anims[MAX_FRAMES_NUM]; /* Array of the ani objs */
} AniObjectInstance;

static int n_frames = MAX_FRAMES_NUM;
static ProAnimFrame *frames;
static AniObjectInstance *ani_obj_seq = NULL; /* Array of  of ani objs */
static int n_objects;                         /* Current number of ani objs */
static const char *p_visit_action_type = "";
static const char *p_filter_action_type = "";
int ProTestAnimframeCreate(void *p_dummy, int int_dummy);
int ProTestAniObjectAdd(void *p_dummy, int int_dummy);
int ProTestSingleAnimation(void *p_dummy, int int_dummy);
ProError ProUtilAniObjectSelect(char option[],
                                ProSelection **p_selection,
                                AniObjectInstance *p_ani_object);
ProError ProUtilSelectedMdlGet(ProSelection *p_selection, ProMdl *p_model);
ProError ProUtilAniObjectInstanceInit(ProSelection **p_selection,
                                      AniObjectInstance *p_ani_object);
ProError ProUtilCollectAnimObjects(ProAnimFrame anim_frame, /* In:  The handle to the animation frame */
                                   ProAnimObj **p_objects   /* Out: ProArray with collected objects.
                                                The function allocates memory
                                                for this argument, but you must
                                                free it. To free the memory,
                                                call the function ProArrayFree()*/
);
ProError ProUtilCollect2ParamDBVisitAction(void *p_object,           /* In:	The pointer to the object being visited */
                                           ProAppData app_data);     /* In:	In fact it's ProArray** */
ProError ProUtilCollect2ParamOpaqueVisitAction(void *p_object,       /* In:	The opaque handle being visited */
                                               ProAppData app_data); /* In:	In fact it's ProArray** */
void TopWindow(HWND &hWnd)
{
    SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
string int2str(int i)
{
    ostringstream os;
    os << i;
    string ret;
    ret = os.str();
    return ret;
}

#if Asynchronous
//异步模式
int main(int argc, char *argv[])
{
    HWND hWnd = GetForegroundWindow();
    // TopWindow(hWnd);
    GetDllPath(dllpath);
    for (int i = 0; i < 3; i++)
    {
        LogFile[i] = dllpath + LogFile[i];
    }
    initLogger(LogFile[0], LogFile[1], LogFile[2]);
    cout << "Connecting..." << endl;
    pfcAsyncConnection_ptr connection;
    try
    {
        connection = pfcAsyncConnection::Connect(NULL, NULL, NULL, 10);
        cout << "Connect Success." << endl;
        pfcSession_ptr session = connection->GetSession();
        while (1)
        {
            cout << "action?";
            char flag = 'Y';
            cin >> flag;
            if (flag == 'Y')
                Async_Action(session);
            else
                break;
        }
    }
    OTK_EXCEPTION_PRINT_LOG
    catch (...)
    {
        cout << "Connect Failed!" << endl;
    }
    system("pause");
    if (connection)
        connection->Disconnect(10);
    cleanlog();
    return 0;
}
#else
//程序入口
extern "C" int user_initialize(
    int argc,
    char *argv[],
    char *version[],
    char *build,
    wchar_t errbuf[80])
{

    GetDllPath(dllpath);
    for (int i = 0; i < 3; i++)
    {
        LogFile[i] = dllpath + LogFile[i];
    }
    initLogger(LogFile[0], LogFile[1], LogFile[2]);

    pfcSession_ptr session = pfcGetProESession();
    try
    {
        //名字首尾字母不要重复，避免快捷键冲突
        xstring Command[] = {"Action"};
        myCallback ComClass[] = {Action};

        for (int i = 0; i < sizeof(Command) / sizeof(Command[0]); i++)
        {
            xstring ComName = Command[i] + "_com";
            xstring Mapkey = "o" + Command[i].Substring(0, 1) + Command[i].Substring(Command[i].GetLength() - 1, -1);
            CreateUICommand(session, ComName, new MycallbackClass(ComClass[i]),
                            MSGFILE, Command[i], Command[i], Command[i],
                            new MyActionAccess(pfcACCESS_AVAILABLE));
            //设置快捷键
            session->SetConfigOption("mapkey", Mapkey + " @MAPKEY_LABEL" + Command[i] + "; ~ Command `" + ComName + "`;");
        }
        session->SetConfigOption("mapkey", "st @MAPKEY_LABEL start" + xstring(ProjectName) +
                                               "; ~ Activate `main_dlg_cur` `page_Tools_control_btn` 1; ~ Command `ProCmdUtilAux`; ~ Select `aux_apps` `AppList` 1 `" +
                                               xstring(ProjectName) + "`; ~ Activate `aux_apps` `StartBtn`; ~ Activate `aux_apps` `CloseBtn`;");
        session->SetConfigOption("mapkey", "sp @MAPKEY_LABEL stop" + xstring(ProjectName) +
                                               "; ~ Activate `main_dlg_cur` `page_Tools_control_btn` 1; ~ Command `ProCmdUtilAux`; ~ Select `aux_apps` `AppList` 1 `" +
                                               xstring(ProjectName) + "`;~ Activate `aux_apps` `StopBtn`; ~ Activate `aux_apps` `CloseBtn`;");
    }
    OTK_EXCEPTION_PRINT_LOG
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }

    return 0;
}
//程序出口
extern "C" void user_terminate()
{
    cleanlog();
}
#endif

int Async_Action(pfcSession_ptr session)
{
    // ProTestAnimframeCreate(nullptr, 0);
    // ProTestAniObjectAdd(nullptr, 0);
    // ProTestSingleAnimation(nullptr, 0);
    Action();
    /*
    // session->AddActionListener(new ParamActionListener());
    session->RunMacro("~ Command `ProCmdDToolsMotion` ;~ Select `anlmotion` `MotionParamList` 2 `1:-2` `2:-2`;~ Activate `anlmotion` `RunButton`;");
    for (int i = 0; i < 10; i++)
    {
        ProWSImpexMessage *message;
        ProCurrentWorkspaceImpexMessagesGet(&message);
        ProWSImpexMessageType type;
        ProPath path;
        ProComment description, resolution;
        ProBoolean succ;
        ProWsimpexmessageDataGet(message[0], &type, path, description, resolution, &succ);
        cout << "path:" << *path << endl;
        cout << "description:" << *description << endl;
        cout << "resolution:" << *resolution << endl;
        cout << "data:" << i << endl;
        // Sleep(1000);
    }
    */
    return 0;
}

wfcStatus Action()
{
    pfcSession_ptr session = pfcGetProESession();
    try
    {
        // ProTestAnimframeCreate(nullptr, 0);
        // ProTestAniObjectAdd(nullptr, 0);
        // ProTestSingleAnimation(nullptr, 0);

        ProError status = PRO_TK_NO_ERROR;
        ProMatrix position = {{-9.964736962657e-001, -1.387778780781e-017, -8.390573669661e-002, 0.0},
                              {8.390573669661e-002, 0.000000000000e+000, -9.964736962657e-001, 0.0},
                              {1.382885051284e-017, -1.000000000000e+000, 1.164426009734e-018, 0.0},
                              {65.0, 43.0, 104.5, 1.0}};
        // ProVector p_x = {1.0, 0.0, 0.0};
        // ProVector p_y = {0.0, 1.0, 0.0};
        // ProVector p_z = {0.0, 0.0, 1.0};
        // ProPoint3d p_o = {65.0, 43.0, 104.5};
        ProVector p_x = {-9.964736962657e-001, -1.387778780781e-017, -8.390573669661e-002};
        ProVector p_y = {8.390573669661e-002, 0.000000000000e+000, -9.964736962657e-001};
        ProVector p_z = {1.382885051284e-017, -1.000000000000e+000, 1.164426009734e-018};
        ProPoint3d p_o = {65.0, 43.0, 104.5};
        // ProVector p_x = {cos(PI / 4), sin(PI / 4), 0.0};
        // ProVector p_y = {-sin(PI / 4), cos(PI / 4), 0.0};
        // ProVector p_z = {0.0, 0.0, 1.0};
        // ProPoint3d p_o = {65.0, 43.0, 104.5};

        ProMatrix frame_view = {{1.0, 0.0, 0.0, 0.0},
                                {0.0, 1.0, 0.0, 0.0},
                                {0.0, 0.0, 1.0, 0.0},
                                {0.0, 0.0, 0.0, 1.0}};
        // ProVector f_x = {-9.78E-01, -5.55E-17, -2.09E-01};
        // ProVector f_y = {2.09E-01, 2.22E-16, -9.78E-01};
        // ProVector f_z = {1.01E-16, -1.00E+00, -2.06E-16};
        // ProPoint3d f_o = {-1.03E-01, 4.24E+01, -1.95E+01};
        // ProVector f_x = {1.0, 0.0, 0.0};
        // ProVector f_y = {0.0, 1.0, 0.0};
        // ProVector f_z = {0.0, 0.0, 1.0};
        // ProPoint3d f_o = {0.0, 0.0, 0.0};
        ProVector f_x = {-9.997749919183e-001, -5.204170427930e-018, -2.121239106608e-002};
        ProVector f_y = {2.121239106608e-002, 2.220446049250e-016, -9.997749919183e-001};
        ProVector f_z = {9.913096441308e-018, -1.000000000000e+000, -2.218842501961e-016};
        ProPoint3d f_o = {65.0, 43.0, 104.5};
        ProSelection *p_sels = NULL;
        // status = ProArrayAlloc(0, sizeof(ProSelection), 1, (ProArray *)p_sel);
        // TEST_CALL_REPORT("ProArrayAlloc()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // status = ProArraySizeSet((ProArray *)p_sel, 1);
        // TEST_CALL_REPORT("ProArraySizeSet()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // xint n_sel;
        // status = ProSelect((char *)"feature", 1, NULL, NULL, NULL, NULL, &p_sel, &n_sel);
        // TEST_CALL_REPORT("ProSelect()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // LOG(LOG_INFO) << n_sel;
        ProMdl p_model;
        status = ProMdlCurrentGet(&p_model);
        TEST_CALL_REPORT("ProMdlCurrentGet()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // ProFeature p_feat;
        // status = ProFeatureInit((ProSolid)p_model, 21, &p_feat);
        // TEST_CALL_REPORT("ProFeatureInit()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        ProAsmcomppath p_path;
        // status = ProMdlVariantfeatAsmcomppathGet(p_model, p_path);
        // status = ProSelectionAsmcomppathGet(p_sel[0], &p_path);
        ProIdTable p_id;
        p_id[0] = 21;
        int table_size = 1;
        // status = ProArrayAlloc(0, sizeof(ProIdTable), 1, (ProArray *)p_id);
        // TEST_CALL_REPORT("ProArrayAlloc()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // status = ProArraySizeSet((ProArray *)p_id, table_size);
        // TEST_CALL_REPORT("ProArraySizeSet()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // status = ProArrayObjectAdd((ProArray *)p_id, 0, 1, (void *)19);
        // TEST_CALL_REPORT("ProArrayObjectAdd()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        status = ProAsmcomppathInit((ProSolid)p_model, p_id, table_size, &p_path);
        TEST_CALL_REPORT("ProAsmcomppathInit()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);

        LOG(LOG_INFO);
        ProModelitem model_item;
        // status = ProSelectionModelitemGet(*p_sel, &model_item);
        status = ProModelitemInit(p_model, p_id[0], PRO_FEATURE, &model_item);
        TEST_CALL_REPORT("ProModelitemInit()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        ProName name;
        char *cname;
        status = ProModelitemNameGet(&model_item, name);
        ProWstringToString(cname, name);
        LOG(LOG_INFO) << *cname;
        LOG(LOG_INFO);
        ProSelection p_sel = NULL;
        status = ProSelectionAlloc(&p_path, &model_item, p_sels);
        TEST_CALL_REPORT("ProSelectionAlloc()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        LOG(LOG_INFO);
        // if (n_sel > 0)
        // {
        ProAnimFrame *anim_frame;
        status = ProArrayAlloc(0, sizeof(ProAnimFrame), 1, (ProArray *)&anim_frame);
        TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        status = ProArraySizeSet((ProArray *)&anim_frame, MAX_FRAMES_NUM);
        TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        status = ProMatrixInit(f_x, f_y, f_z, f_o, frame_view);
        TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        for (int fi = 0; fi < 4; fi++)
            LOG(LOG_INFO) << frame_view[fi][0] << "\t"
                          << frame_view[fi][1] << "\t"
                          << frame_view[fi][2] << "\t"
                          << frame_view[fi][3];
        status = ProAnimframeCreate(frame_view, &(anim_frame[0]));
        TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);

        ProAnimObj *anim_obj;
        status = ProArrayAlloc(0, sizeof(ProAnimObj), 1, (ProArray *)&anim_obj);
        TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        status = ProArraySizeSet((ProArray *)&anim_obj, MAX_FRAMES_NUM);
        TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // status = ProMatrixInit(p_x, p_y, p_z, p_o, position);
        // TEST_CALL_REPORT("ProAnimframeCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // for (int fi = 0; fi < 4; fi++)
        //     LOG(LOG_INFO) << position[fi][0] << "\t"
        //                   << position[fi][1] << "\t"
        //                   << position[fi][2] << "\t"
        //                   << position[fi][3];
        status = ProAnimobjectCreate(p_sels[0], position, &(anim_obj[0]));
        TEST_CALL_REPORT("ProAnimobjectCreate()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);

        status = ProAnimframeObjAdd(anim_frame[0], anim_obj[0]);
        TEST_CALL_REPORT("ProAnimframeObjAdd()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);

        // ProModelitem model_item;
        // status = ProSelectionModelitemGet(p_sel[0], &model_item);
        // status = ProModelitemMdlGet(&model_item, &p_model);
        // TEST_CALL_REPORT("ProModelitemMdlGet()", "Action()", status, status != PRO_TK_NO_ERROR);
        // TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);

        ProSingleAnim single_anim_obj;
        ProSingleAnimationInit(p_model, anim_frame[0], &single_anim_obj);
        TEST_CALL_REPORT("ProSingleAnimationInit()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);

        ProSingleAnimationPlay(single_anim_obj, anim_frame[0]);
        TEST_CALL_REPORT("ProSingleAnimationPlay()", "Action()", status, status != PRO_TK_NO_ERROR);
        TEST_CALL_EXIT(status != PRO_TK_NO_ERROR);
        // }

        /*
        session->AddActionListener(new ParamActionListener());
        session->RunMacro("~ Command `ProCmdDToolsMotion` ;~ Select `anlmotion` `MotionParamList` 2 `1:-2` `2:-2`;~ Activate `anlmotion` `RunButton`;");
        for (int i = 0; i < 10; i++)
        {
            xstringsequence_ptr stringseq = xstringsequence::create();
            stringseq->append(int2str(i).c_str());
            session->UIDisplayMessage(MSGFILE, "Data:%0s", stringseq);
            Sleep(1000);
        }

        //     ProError err;
        //     ProSelection *sel;
        //     int n_sel;

        //     err = ProSelect((char *)"sim_connect", 1, NULL, NULL, NULL, NULL, &sel, &n_sel);
        //     if (err != PRO_TK_NO_ERROR || n_sel < 1)
        //     {
        //         LOG(LOG_ERROR) << "select err:" << err << endl;
        //         return wfcTK_NO_ERROR;
        //     }
        //     ProFeature feature;
        //     ProSelectionModelitemGet(sel[0], &feature);
        //     LOG(LOG_INFO) << "type:" << feature.type;
        */
    }
    OTK_EXCEPTION_PRINT_LOG
    catch (...)
    {
        cout << "List Windows Failed!\n";
    }
    return wfcTK_NO_ERROR;
}
int Action(pfcSession_ptr session)
{
    try
    {
        while (1)
        {
            char flag = 'Y';
            cout << "Action?(Y/N)";
            cin >> flag;
            if (flag != 'Y')
                break;

            session->AddActionListener(new ParamActionListener());
            // pfcWindows_ptr windows = session->ListWindows();
            // int count = windows->getarraysize();
            // if (count > 0)
            // {
            //     for (int i = 0; i < count; i++)
            //     {
            //         cout << "win" << i << ":" << windows->get(i)->GetId();
            //         cout << endl;
            //     }
            // }
        }
    }
    OTK_EXCEPTION_PRINT_LOG
    catch (...)
    {
        cout << "List Windows Failed!\n";
    }
    return wfcTK_NO_ERROR;
}
/*
wfcStatus Action(pfcSession_ptr session)
{
    try
    {
        //选择一个模型
        cout << "Please Selected Commponent:" << endl;
        pfcSelectionOptions_ptr opts = pfcSelectionOptions::Create("feature");
        opts->SetMaxNumSels(1);
        pfcSelections_ptr sels = session->Select(opts);
        pfcModelItem_ptr ModelItem;
        if (sels != NULL)
        {
            ModelItem = sels->get(0)->GetSelItem();
            pfcFeature_ptr feat = pfcFeature::cast(ModelItem);
            cout << feat->GetType() << ":" << feat->GetFeatTypeName() << endl;
            cout << feat << endl;

            pfcComponentFeat_ptr Cfeat = pfcComponentFeat::cast(feat);
            cout << endl;
            for (int t = 0; t < 10; t++)
            {
                Sleep(1000);
                pfcTransform3D_ptr Trans = Cfeat->GetPosition();
                pfcPoint3D_ptr Origin = Trans->GetOrigin();
                cout << "O:" << Origin->get(0) << "\t"
                     << Origin->get(1) << "\t"
                     << Origin->get(0) << endl;
                pfcMatrix3D_ptr Matrix = Trans->GetMatrix();
                for (int i = 0; i < 4; i++)
                {
                    cout << "M" << i << ":" << Matrix->get(i, 0) << "\t"
                         << Matrix->get(i, 1) << "\t"
                         << Matrix->get(i, 2) << "\t"
                         << Matrix->get(i, 3) << endl;
                }
            }

        }
    }
    OTK_EXCEPTION_PRINT_LOG
    return wfcTK_NO_ERROR;
}
*/
void cleanlog()
{
    LOG(LOG_FATAL); //触发logger析构函数
    fstream file;
    for (int i = 0; i < 3; i++)
    {
        file.open(LogFile[i], ios::in);
        if (file.get() == EOF)
        {
            file.close();
            file.clear();
            _FileExt emptyfile(LogFile[i].c_str());
            DeleteFileA(emptyfile.fullname.c_str());
        }
        else
        {
            file.close();
            file.clear();
        }
    }
}

void ParamActionListener::OnBeforeParameterCreate(pfcModel_ptr Owner,
                                                  xrstring Name,
                                                  pfcUnit_ptr Units,
                                                  pfcParamValue_ptr Value)
{
    cout << "beforeparamcreate:" << Name << "--" << Value->Getdiscr() << endl;
    LOG(LOG_INFO) << "beforeparamcreate:" << Name << "--" << Value->Getdiscr();
}

void ParamActionListener::OnBeforeParameterModify(pfcParameter_ptr Param,
                                                  pfcUnit_ptr NewUnits,
                                                  pfcParamValue_ptr NewValue,
                                                  pfcUnit_ptr OldUnits,
                                                  pfcParamValue_ptr OldValue)
{
    cout << "beforemodify:" << Param->GetName() << endl;
    LOG(LOG_INFO) << "beforemodify:" << Param->GetName();
}

void FeatureParamListener::OnBeforeParameterCreate(pfcFeature_ptr Owner,
                                                   xrstring Name,
                                                   pfcUnit_ptr Units,
                                                   pfcParamValue_ptr Value)
{
    LOG(LOG_INFO) << "beforefeaturecreate:" << Name;
}
void FeatureParamListener::OnBeforeParameterModify(pfcParameter_ptr Param,
                                                   pfcUnit_ptr NewUnits,
                                                   pfcParamValue_ptr NewValue,
                                                   pfcUnit_ptr OldUnits,
                                                   pfcParamValue_ptr OldValue)
{
    LOG(LOG_INFO) << "beforefeatureParamModify:" << Param->GetName();
}
int ProTestAnimframeCreate(void *p_dummy, int int_dummy)
{
    ProError status;
    int i;
    ProMatrix m_frame_view = {
        {1.0, 0.0, 0.0, 0.0},
        {0.0, 1.0, 0.0, 0.0},
        {0.0, 0.0, 1.0, 0.0},
        {0.0, 0.0, 0.0, 1.0}};
    ProVector v_x = {1.0, 0.0, 0.0};
    ProVector v_y = {0.0, 1.0, 0.0};
    ProVector v_z = {0.0, 0.0, 1.0};
    ProPoint3d origin = {0.0, 0.0, 1.0};
    status = ProArrayAlloc(0, sizeof(ProAnimFrame), 1, (ProArray *)&frames);
    TEST_CALL_REPORT("ProArrayAlloc()", "ProTestAnimation()",
                     status, status != PRO_TK_NO_ERROR);
    if (status != PRO_TK_NO_ERROR)
        return -1;
    status = ProArraySizeSet((ProArray *)&frames, n_frames);
    TEST_CALL_REPORT("ProArraySizeSet()", "ProTestAnimation()",
                     status, status != PRO_TK_NO_ERROR);

    /* Init the frame view matrix */
    // status = ProMatrixInit(v_x, v_y, v_z, origin, m_frame_view);
    for (int ii = 0; ii < 4; ii++)
        LOG(LOG_INFO) << m_frame_view[ii][0] << "\t" << m_frame_view[ii][1] << "\t" << m_frame_view[ii][2] << "\t" << m_frame_view[ii][3];
    TEST_CALL_REPORT("ProMatrixInit()", "ProTestAnimframeCreate()",
                     status, status != PRO_TK_NO_ERROR);

    /* Initialize the frames */
    for (i = 0; i < n_frames; i++)
    {
        status = ProAnimframeCreate(m_frame_view, &(frames[i]));
        TEST_CALL_REPORT("ProAnimframeCreate()", "ProTestAnimframeCreate()",
                         status, status != PRO_TK_NO_ERROR);
    }

    return 0; /* Upon success */
}

int ProTestAniObjectAdd(void *p_dummy, int int_dummy)
{
    ProError status;
    ProSelection *p_selection;
    AniObjectInstance ani_object; /* Created animation object */
    int i_frame;
    double angle;
    double add_angle;
    ProMode mode;
    ProMatrix m_transform = {
        {1.0, 0.0, 0.0, 0.0},
        {0.0, 1.0, 0.0, 0.0},
        {0.0, 0.0, 1.0, 0.0},
        {0.0, 5.0, 0.0, 1.0}};

    /* Select ONE element to animate */

    status = ProUtilAniObjectSelect((char *)"prt_or_asm", &p_selection, &ani_object);
    TEST_CALL_REPORT("ProUtilAniObjectSelect()", "ProTestAniObjectAdd()",
                     status, status != PRO_TK_NO_ERROR);
    // if (status == PRO_TK_USER_ABORT)
    //     return -1;
    // if (status != PRO_TK_E_NOT_FOUND)
    // {
    //     /* User have selected already animated object */
    //     // ProUtilMsgPrint("gen", "TEST %0s", "The item is already animated");
    //     return -1;
    // }
    /* Init the array of animation objects */
    n_objects = 0;
    status = ProArrayAlloc(0, sizeof(AniObjectInstance), 1, (ProArray *)&ani_obj_seq);
    TEST_CALL_REPORT("ProArrayAlloc()", "ProTestAnimation()",
                     status, status != PRO_TK_NO_ERROR);

    /* Insert object to the array of the animated elements */
    status = ProArrayObjectAdd((ProArray *)&ani_obj_seq, 0, 1, (void *)&ani_object);
    TEST_CALL_REPORT("ProArrayObjectAdd()", "ProTestAniObjectAdd()",
                     status, status != PRO_TK_NO_ERROR);
    if (status == PRO_TK_NO_ERROR)
        n_objects++;
    else
        return -1;

    status = ProModeCurrentGet(&mode);
    TEST_CALL_REPORT("ProModeCurrentGet()", "ProTestAniObjectAdd()",
                     status, status != PRO_TK_NO_ERROR);
    if (mode == PRO_MODE_ASSEMBLY)
    {
        /* Retrieve the transformation matrix */
        status = ProAsmcomppathTrfGet(&ani_obj_seq[0].comp_path,
                                      PRO_B_TRUE, m_transform);
        TEST_CALL_REPORT("ProAsmcomppathTrfGet()", "ProTestAniObjectAdd()",
                         status, status != PRO_TK_NO_ERROR);

        /* Assign the transformation matrix. Used for test only */
        status = ProAsmcomppathTrfSet(&ani_obj_seq[0].comp_path,
                                      PRO_B_TRUE, m_transform);
        TEST_CALL_REPORT("ProAsmcomppathTrfSet()", "ProTestAniObjectAdd()",
                         status, status != PRO_TK_NO_ERROR);
    }

    /* Create animation objects and add it to the frames */
    for (i_frame = 0; i_frame < n_frames; i_frame++)
    {

        /* Create an animation object... */
        status = ProAnimobjectCreate(*p_selection, m_transform,
                                     &ANI_OBJECT(0, i_frame));
        TEST_CALL_REPORT("ProAnimobjectCreate()", "ProTestAniObjectAdd()",
                         status, status != PRO_TK_NO_ERROR);
        if (status != PRO_TK_NO_ERROR)
            return -1;

        /* ...and add it to the frame */
        status = ProAnimframeObjAdd(frames[i_frame], ANI_OBJECT(0, i_frame));
        TEST_CALL_REPORT("ProAnimframeObjAdd()", "ProTestAniObjectAdd()",
                         status, status != PRO_TK_NO_ERROR);
        if (status != PRO_TK_NO_ERROR)
            return -1;
    }

    return 0;
}
int ProTestSingleAnimation(void *p_dummy, int int_dummy)
{
    ProError status;
    ProSingleAnim single_animation;
    int i_frame;
    int i_obj;
    ProAnimObj *anim_objects;
    int anim_obj_num, i;

    /* Initialize an animation in single mode. */
    status = ProSingleAnimationInit(ani_obj_seq[0].model,
                                    frames[0], &single_animation);
    TEST_CALL_REPORT("ProSingleAnimationInit()", "ProTestSingleAnimation()",
                     status, status != PRO_TK_NO_ERROR);
    if (status != PRO_TK_NO_ERROR)
        return -1;

    /* Play back the animation frame by frame */
    for (i_frame = 0; i_frame < n_frames; i_frame++)
    {
        /* Play back the frame */
        status = ProSingleAnimationPlay(single_animation, frames[i_frame]);
        TEST_CALL_REPORT("ProSingleAnimationPlay()",
                         "ProTestSingleAnimation()",
                         status, status != PRO_TK_NO_ERROR);
        if (status != PRO_TK_NO_ERROR)
            return -1;
    }

    /* Visit objects in the frames */
    puts("Visit objects in the frames:");
    cout << "n_frames:" << n_frames << "\tn_objects:" << n_objects << endl;
    for (i_frame = 0; i_frame < n_frames; i_frame++)
        for (i_obj = 0; i_obj < n_objects; i_obj++)
        {
            LOG(LOG_INFO);
            status = ProUtilCollectAnimObjects(frames[i_frame], &anim_objects);
            TEST_CALL_REPORT("ProUtilCollectAnimObjects()", "ProTestSingleAnimation()",
                             status, status != PRO_TK_NO_ERROR);
            if (status == PRO_TK_NO_ERROR)
            {
                LOG(LOG_INFO);
                status = ProArraySizeGet((ProArray)anim_objects, &anim_obj_num);
                TEST_CALL_REPORT("ProArraySizeGet()", "ProTestSingleAnimation()",
                                 status, status != PRO_TK_NO_ERROR);
                // for (i = 0; i < anim_obj_num; i++)
                // {
                //     status = ProTestSingleAnimAct(anim_objects[i],
                //                                   (ProAppData)&i_frame);
                // }
                LOG(LOG_INFO);
                status = ProArrayFree((ProArray *)&anim_objects);
                TEST_CALL_REPORT("ProArrayFree()", "ProTestSingleAnimation()",
                                 status, status != PRO_TK_NO_ERROR);
            }
        }
    LOG(LOG_INFO);
    /* Clear the data generated for single mode animation.*/
    status = ProSingleAnimationClear(single_animation);
    TEST_CALL_REPORT("ProSingleAnimationClear()",
                     "ProTestSingleAnimation()",
                     status, status != PRO_TK_NO_ERROR);
    // if (status != PRO_TK_NO_ERROR)
    //     return -1;

    return 0;
}
ProError ProUtilAniObjectSelect(char option[],                   /* (In)	The selection filter. */
                                ProSelection **p_selection,      /* (Out)	The pointer to selected item */
                                AniObjectInstance *p_ani_object) /* (Out)    Animation object to initialize. Can be NULL */
{
    ProError status;
    int n_selected = 0; /* Actual number of sections made. */
    AniObjectInstance ani_object;

    /* Check arguments */
    if (!p_selection)
        return PRO_TK_USER_ABORT;

    /* Select ONE object. */
    status = ProSelect(option, 1,
                       NULL, NULL, NULL, NULL, p_selection, &n_selected);
    TEST_CALL_REPORT("ProSelect()", "ProUtilAniObjectSelect()",
                     status, status != PRO_TK_NO_ERROR);
    if ((status != PRO_TK_NO_ERROR) || (n_selected != 1))
        return PRO_TK_USER_ABORT;

    if (p_ani_object == NULL)
        p_ani_object = &ani_object;

    /* Use ProSelection data to init the animation object */
    if (ProUtilAniObjectInstanceInit(p_selection, p_ani_object) != PRO_TK_NO_ERROR)
        return PRO_TK_USER_ABORT;

    /* Try to find out the selected object among array of the
    animation objects */
    return PRO_TK_NO_ERROR;
}

ProError ProUtilAniObjectInstanceInit(
    ProSelection **p_selection,      /* (In)	    The pointer to selected item */
    AniObjectInstance *p_ani_object) /* (Out)	Animation object to init */
{
    ProError status;

    /* Get a model from the selection */
    if (ProUtilSelectedMdlGet(*p_selection, &(p_ani_object->model)) != PRO_TK_NO_ERROR)
        return PRO_TK_GENERAL_ERROR;

    /* Get a component path of the model */
    status = ProSelectionAsmcomppathGet(**p_selection,
                                        &(p_ani_object->comp_path));
    TEST_CALL_REPORT("ProSelectionAsmcomppathGet()",
                     "ProUtilAniObjectInstanceInit()",
                     status, status != PRO_TK_NO_ERROR);
    if (status != PRO_TK_NO_ERROR)
        return PRO_TK_GENERAL_ERROR;

    return PRO_TK_NO_ERROR;
}
ProError ProUtilSelectedMdlGet(ProSelection *p_selection, ProMdl *p_model)
{
    ProError status;
    ProModelitem model_item;

    /* Check out the input parameters */
    if (!p_selection || !p_model)
        return PRO_TK_GENERAL_ERROR;

    /* Get the model item from a selection object. */
    status = ProSelectionModelitemGet(*p_selection, &model_item);
    TEST_CALL_REPORT("ProSelectionModelitemGet()", "ProUtilSelectedMdlGet()",
                     status, status != PRO_TK_NO_ERROR);
    if (status == PRO_TK_NO_ERROR)
    {
        /* Retrieve the model the owns the specified item. */
        status = ProModelitemMdlGet(&model_item, p_model);
        TEST_CALL_REPORT("ProModelitemMdlGet()", "ProUtilSelectedMdlGet()",
                         status, status != PRO_TK_NO_ERROR);
        if (status == PRO_TK_NO_ERROR)
            return PRO_TK_NO_ERROR;
    }

    return PRO_TK_GENERAL_ERROR;
}
ProError ProUtilCollectAnimObjects(
    ProAnimFrame anim_frame, /* In:  The handle to the animation
                 frame */
    ProAnimObj **p_objects   /* Out: ProArray with collected objects.
                 The function allocates memory
                 for this argument, but you must
                 free it. To free the memory,
                 call the function ProArrayFree()*/
)
{
    ProError status;

    if (p_objects != NULL)
    {
        LOG(LOG_INFO);
        status = ProArrayAlloc(0, sizeof(ProAnimObj), 1, (ProArray *)p_objects);
        TEST_CALL_REPORT("ProArrayAlloc()", "ProUtilCollectAnimObjects()",
                         status, status != PRO_TK_NO_ERROR);
        if (status == PRO_TK_NO_ERROR)
        {
            LOG(LOG_INFO);
            ACTION_TYPE("ProAnimObjAct", "ProAnimObjAct")
            status = ProAnimframeObjVisit(anim_frame,
                                          (ProAnimObjAct)ProUtilCollect2ParamOpaqueVisitAction,
                                          (ProAnimObjAct)PRO_TK_NO_ERROR,
                                          (ProAppData)&p_objects);
            LOG(LOG_INFO);
            TEST_CALL_REPORT("ProAnimframeObjVisit()",
                             "ProUtilCollectAnimObjects()", status,
                             status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
            if (status != PRO_TK_NO_ERROR)
            {
                LOG(LOG_INFO);
                ProArrayFree((ProArray *)p_objects);
                *p_objects = NULL;
            }
        }
    }
    else
        status = PRO_TK_BAD_INPUTS;

    return (status);
}
ProError ProUtilCollect2ParamDBVisitAction(void *p_object,      /* In:	The pointer to the object being visited */
                                           ProAppData app_data) /* In:	In fact it's ProArray** */
{
    ProError status;
    ProArray *p_array;

    p_array = (ProArray *)((void **)app_data)[0];

    TEST_CALL_REPORT(p_visit_action_type, "ProUtilCollect2ParamDBVisitAction",
                     PRO_TK_NO_ERROR, 0);

    LOG(LOG_INFO);
    status = ProArrayObjectAdd(p_array, PRO_VALUE_UNUSED, 1, p_object);
    TEST_CALL_REPORT("ProArrayObjectAdd()", "ProUtilCollect2ParamDBVisitAction", status, status != PRO_TK_NO_ERROR);
    LOG(LOG_INFO);
    return (status);
}
ProError ProUtilCollect2ParamOpaqueVisitAction(
    void *p_object,      /* In:	The opaque handle being visited */
    ProAppData app_data) /* In:	In fact it's ProArray** */
{
    return (ProUtilCollect2ParamDBVisitAction((void *)&p_object, app_data));
}